<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  <title>python多线程再研究 | Jin Tian</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  
  
  
  
  <meta name="description" content="继上一篇多线程文章之后，继续研究Python多线程并发 多线程在创作大型程序的过程中显得尤为重要，在开发Jarvis的过程中，我一直找不到一个合适的方法去让他在不妨碍主线程的情况之下去执行任意程序。实际上这就完全可以用多线程来解决，听起来非常简单，但实际上不然。真正做起来还是有点麻烦。这篇文章我们将继续梳理python多线程  抛弃multiporcess使用Threading上一篇文章中我讲到了">
<meta property="og:type" content="article">
<meta property="og:title" content="Python多线程再研究">
<meta property="og:url" content="http://yoursite.com/2017/04/28/Python多线程再研究/index.html">
<meta property="og:site_name" content="Jin Tian">
<meta property="og:description" content="继上一篇多线程文章之后，继续研究Python多线程并发 多线程在创作大型程序的过程中显得尤为重要，在开发Jarvis的过程中，我一直找不到一个合适的方法去让他在不妨碍主线程的情况之下去执行任意程序。实际上这就完全可以用多线程来解决，听起来非常简单，但实际上不然。真正做起来还是有点麻烦。这篇文章我们将继续梳理python多线程  抛弃multiporcess使用Threading上一篇文章中我讲到了">
<meta property="og:locale" content="zh-CN">
<meta property="og:updated_time" content="2017-04-28T06:54:13.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Python多线程再研究">
<meta name="twitter:description" content="继上一篇多线程文章之后，继续研究Python多线程并发 多线程在创作大型程序的过程中显得尤为重要，在开发Jarvis的过程中，我一直找不到一个合适的方法去让他在不妨碍主线程的情况之下去执行任意程序。实际上这就完全可以用多线程来解决，听起来非常简单，但实际上不然。真正做起来还是有点麻烦。这篇文章我们将继续梳理python多线程  抛弃multiporcess使用Threading上一篇文章中我讲到了">
  
    <link rel="alternate" href="/atom.xml" title="Jin Tian" type="application/atom+xml">
  

  

  <link rel="icon" href="/css/images/mylogo.jpg">
  <link rel="apple-touch-icon" href="/css/images/mylogo.jpg">
  
    <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  
  <link href="https://fonts.googleapis.com/css?family=Open+Sans|Montserrat:700" rel="stylesheet" type="text/css">
  <link href="https://fonts.googleapis.com/css?family=Roboto:400,300,300italic,400italic" rel="stylesheet" type="text/css">
  <link href="//cdn.bootcss.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet">
  <style type="text/css">
    @font-face{font-family:futura-pt;src:url(https://use.typekit.net/af/9749f0/00000000000000000001008f/27/l?subset_id=2&fvd=n5) format("woff2");font-weight:500;font-style:normal;}
    @font-face{font-family:futura-pt;src:url(https://use.typekit.net/af/90cf9f/000000000000000000010091/27/l?subset_id=2&fvd=n7) format("woff2");font-weight:500;font-style:normal;}
    @font-face{font-family:futura-pt;src:url(https://use.typekit.net/af/8a5494/000000000000000000013365/27/l?subset_id=2&fvd=n4) format("woff2");font-weight:lighter;font-style:normal;}
    @font-face{font-family:futura-pt;src:url(https://use.typekit.net/af/d337d8/000000000000000000010095/27/l?subset_id=2&fvd=i4) format("woff2");font-weight:400;font-style:italic;}</style>
  <link rel="stylesheet" href="/css/style.css">

  <script src="/js/jquery-3.1.1.min.js"></script>
  <script src="/js/bootstrap.js"></script>

  <!-- Bootstrap core CSS -->
  <link rel="stylesheet" href="/css/bootstrap.css" >

  
    <link rel="stylesheet" href="/css/dialog.css">
  

  

  
    <link rel="stylesheet" href="/css/header-post.css" >
  

  
  
  
    <link rel="stylesheet" href="/css/vdonate.css" >
  

</head>



  <body data-spy="scroll" data-target="#toc" data-offset="50">


  
  <div id="container">
    <div id="wrap">
      
        <header>

    <div id="allheader" class="navbar navbar-default navbar-static-top" role="navigation">
        <div class="navbar-inner">
          
          <div class="container"> 
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
              <span class="sr-only">Toggle navigation</span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
              <span class="icon-bar"></span>
            </button>

            
              <a class="brand" style="
                 border-width: 0px;  margin-top: 0px;"  
                href="#" data-toggle="modal" data-target="#myModal" >
                  <img width="124px" height="124px" alt="Hike News" src="/css/images/mylogo.jpg">
              </a>
            
            
            <div class="navbar-collapse collapse">
              <ul class="hnav navbar-nav">
                
                  <li> <a class="main-nav-link" href="/">首页</a> </li>
                
                  <li> <a class="main-nav-link" href="/archives">归档</a> </li>
                
                  <li> <a class="main-nav-link" href="/categories">分类</a> </li>
                
                  <li> <a class="main-nav-link" href="/tags">标签</a> </li>
                
                  <li> <a class="main-nav-link" href="/about">关于</a> </li>
                
                  <li> <a class="main-nav-link" href="http://luoli-luoli.com/chat">chat</a> </li>
                
                  <li><div id="search-form-wrap">

    <form class="search-form">
        <input type="text" class="ins-search-input search-form-input" placeholder="" />
        <button type="submit" class="search-form-submit"></button>
    </form>
    <div class="ins-search">
    <div class="ins-search-mask"></div>
    <div class="ins-search-container">
        <div class="ins-input-wrapper">
            <input type="text" class="ins-search-input" placeholder="请输入关键词..." />
            <span class="ins-close ins-selectable"><i class="fa fa-times-circle"></i></span>
        </div>
        <div class="ins-section-wrapper">
            <div class="ins-section-container"></div>
        </div>
    </div>
</div>
<script>
(function (window) {
    var INSIGHT_CONFIG = {
        TRANSLATION: {
            POSTS: '文章',
            PAGES: '页面',
            CATEGORIES: '分类',
            TAGS: '标签',
            UNTITLED: '(无标题)',
        },
        ROOT_URL: '/',
        CONTENT_URL: '/content.json',
    };
    window.INSIGHT_CONFIG = INSIGHT_CONFIG;
})(window);
</script>
<script src="/js/insight.js"></script>

</div></li>
            </div>
          </div>
                
      </div>
    </div>

</header>



      
            
      <div id="content" class="outer">
        
          <section id="main" style="float:none;"><article id="post-Python多线程再研究" style="width: 75%; float:left;" class="article article-type-post" itemscope itemprop="blogPost" >
  <div id="articleInner" class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 class="thumb" class="article-title" itemprop="name">
      Python多线程再研究
    </h1>
  

      </header>
    
    <div class="article-meta">
      
	<a href="/2017/04/28/Python多线程再研究/" class="article-date">
	  <time datetime="2017-04-28T01:22:39.000Z" itemprop="datePublished">2017-04-28</time>
	</a>

      
      
	<a class="article-views">
	<span id="busuanzi_container_page_pv">
		阅读量<span id="busuanzi_value_page_pv"></span>
	</span>
	</a>

    </div>
    <div class="article-entry" itemprop="articleBody">
      
        <h1 id="继上一篇多线程文章之后，继续研究Python多线程并发"><a href="#继上一篇多线程文章之后，继续研究Python多线程并发" class="headerlink" title="继上一篇多线程文章之后，继续研究Python多线程并发"></a>继上一篇多线程文章之后，继续研究Python多线程并发</h1><blockquote>
<p>多线程在创作大型程序的过程中显得尤为重要，在开发Jarvis的过程中，我一直找不到一个合适的方法去让他在不妨碍主线程的情况之下去执行任意程序。实际上这就完全可以用多线程来解决，听起来非常简单，但实际上不然。真正做起来还是有点麻烦。这篇文章我们将继续梳理python多线程</p>
</blockquote>
<h1 id="抛弃multiporcess使用Threading"><a href="#抛弃multiporcess使用Threading" class="headerlink" title="抛弃multiporcess使用Threading"></a>抛弃multiporcess使用Threading</h1><p>上一篇文章中我讲到了multiprocess这个pyton官方模块，但是这个模块并不好用，不够友好，我们决定使用Threading，Threading看上去更简单，使用方法也和multiprocess一样，threading创建多个线程，然后一一回收，最后甚至可以用一种非常简单的方法回收每个线程的返回值。我直接贴代码如下：</p>
<figure class="highlight python"><table><tr><td class="code"><pre><div class="line"><span class="keyword">import</span> threading</div><div class="line"><span class="keyword">from</span> datetime <span class="keyword">import</span> datetime</div><div class="line"><span class="keyword">import</span> time</div><div class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</div><div class="line"><span class="keyword">import</span> logging</div><div class="line"></div><div class="line">logging.basicConfig(level=logging.DEBUG, format=<span class="string">'(%(threadName)-10s) %(message)s'</span>)</div><div class="line"></div><div class="line">r = []</div><div class="line"></div><div class="line"></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">worker</span><span class="params">(i_, w_)</span>:</span></div><div class="line">    c = <span class="number">0</span></div><div class="line">    p = np.random.randint(<span class="number">0</span>, <span class="number">10</span>)</div><div class="line">    <span class="keyword">while</span> <span class="keyword">True</span>:</div><div class="line">        logging.info(<span class="string">'hello, &#123;&#125;. worker &#123;&#125; now time: &#123;&#125;'</span>.format(w_, i_, datetime.now()))</div><div class="line">        time.sleep(<span class="number">2</span>)</div><div class="line">        c += <span class="number">1</span></div><div class="line">        <span class="keyword">if</span> c &gt; p:</div><div class="line">            <span class="keyword">break</span></div><div class="line">    r.append(p)</div><div class="line"></div><div class="line"></div><div class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</div><div class="line">    threads = []</div><div class="line">    w = [<span class="string">'fuck'</span>, <span class="string">'stupid'</span>, <span class="string">'what are u dong'</span>, <span class="string">'go die'</span>, <span class="string">'god damn it.'</span>]</div><div class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">5</span>):</div><div class="line">        t = threading.Thread(target=worker, args=(i, w[i]))</div><div class="line">        threads.append(t)</div><div class="line">        t.start()</div><div class="line">    <span class="keyword">for</span> t <span class="keyword">in</span> threads:</div><div class="line">        t.join()</div><div class="line">    print(<span class="string">'[last]'</span>)</div><div class="line">    print(r)</div></pre></td></tr></table></figure>
<p>在这个例子中，我们有5个线程，每个线程执行worker里面的函数，但是有中断的条件就是随机一个10以内的数，当循环大于这个数的时候，我们就break。<br>大家运行就会看到，我把所有线程都join到回收池，也就意味着所有线程都执行完了，然后我使用了一个r数组来收集每个线程的返回值，简单吧。</p>
<p>最后就可以直接打印出，每个函数的随机停止的值是多少。</p>
<h1 id="Threading还能干什么"><a href="#Threading还能干什么" class="headerlink" title="Threading还能干什么"></a>Threading还能干什么</h1><p>在上面的例子中，如果我们在实现这么一个多线程的例子：</p>
<blockquote>
<p>有一个主线程，任务是执行print hello，然后在时间到了一分钟之后这个时间点时候就分开一个线程去print ‘我要看黄色笑话’，但是依旧不妨碍主线程的运行，那这个时候我们能不能做到呢？</p>
</blockquote>
<p>事实上完全可以的，我直接贴出我们的例子代码：</p>
<figure class="highlight python"><table><tr><td class="code"><pre><div class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</div><div class="line"><span class="keyword">from</span> datetime <span class="keyword">import</span> datetime</div><div class="line"><span class="keyword">import</span> logging</div><div class="line"><span class="keyword">import</span> time</div><div class="line"><span class="keyword">from</span> threading <span class="keyword">import</span> Thread</div><div class="line"></div><div class="line">logging.basicConfig(level=logging.DEBUG, format=<span class="string">'(%(threadName)-10s) %(message)s'</span>)</div><div class="line"></div><div class="line"></div><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">CruiseBot</span><span class="params">(object)</span>:</span></div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></div><div class="line">        self.name = <span class="string">'Cruise'</span></div><div class="line"></div><div class="line">        self._init_start_time()</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">cruise</span><span class="params">(self)</span>:</span></div><div class="line">        self._main_loop()</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">_init_start_time</span><span class="params">(self)</span>:</span></div><div class="line">        self.start_time = datetime.now().minute</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">_main_loop</span><span class="params">(self)</span>:</span></div><div class="line">        <span class="comment"># this is his main duty job</span></div><div class="line">        <span class="keyword">while</span> <span class="keyword">True</span>:</div><div class="line">            logging.debug(<span class="string">'hello, I am &#123;&#125;, now time is: &#123;&#125;'</span>.format(self.name, datetime.now()))</div><div class="line">            time.sleep(<span class="number">5</span>)</div><div class="line"></div><div class="line">            now = datetime.now().minute</div><div class="line">            <span class="keyword">if</span> now - self.start_time == <span class="number">1</span>:</div><div class="line">                <span class="comment"># 1分钟之后开一个线程执行另外一个事情</span></div><div class="line">                logging.debug(<span class="string">'start execute job 1'</span>)</div><div class="line">                t = Thread(name=<span class="string">'alice'</span>, target=self._thread_job_1, args=(<span class="number">1</span>,))</div><div class="line">                t.start()</div><div class="line">            <span class="keyword">if</span> now - self.start_time == <span class="number">2</span>:</div><div class="line">                <span class="comment"># 2分钟之后开一个线程执行另外一个事情</span></div><div class="line">                logging.debug(<span class="string">'start execute job 2'</span>)</div><div class="line">                t = Thread(name=<span class="string">'bob'</span>, target=self._thread_job_2, args=(<span class="number">2</span>,))</div><div class="line">                t.start()</div><div class="line"></div><div class="line"><span class="meta">    @staticmethod</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">_thread_job_1</span><span class="params">(i)</span>:</span></div><div class="line">        <span class="keyword">while</span> <span class="keyword">True</span>:</div><div class="line">            logging.debug(<span class="string">'thread jobber &#123;&#125;, i am eating hamburg!!!!'</span>.format(i))</div><div class="line">            time.sleep(<span class="number">2</span>)</div><div class="line"></div><div class="line"><span class="meta">    @staticmethod</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">_thread_job_2</span><span class="params">(i)</span>:</span></div><div class="line">        <span class="keyword">while</span> <span class="keyword">True</span>:</div><div class="line">            logging.debug(<span class="string">'thread jobber &#123;&#125;, i am doing say hello'</span>.format(i))</div><div class="line">            time.sleep(<span class="number">2</span>)</div><div class="line"></div><div class="line"></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></div><div class="line">    cruise_bot = CruiseBot()</div><div class="line">    cruise_bot.cruise()</div><div class="line"></div><div class="line"></div><div class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</div><div class="line">    main()</div></pre></td></tr></table></figure>
<p>这个代码有点长，实际上我们只需要关注定义的那个巡航机器人类，在这里祝循环里面它要做一个事情，然后在一分钟后执行第一个子任务，两分钟后执行第二个子任务，可以看到，在这里我们的设定的工作完全执行正常，整个程序从第二分钟开始指定第二个子任务，并且并没有妨碍主线程的执行。这正是我们想要的。</p>
<h1 id="进一步思考"><a href="#进一步思考" class="headerlink" title="进一步思考"></a>进一步思考</h1><p>教程写到这里，我就得进一步思考怎么给Jarvis添加分身的大脑了。Jarvis要实现的功能是当接收到某个指令时，这个指令是让他在某个时间去执行某个事情，怎么才能实现，给他添加一个reminder，当到了那个时间后他就去执行那个事情呢？</p>
<p>首先，让我们来捋一下思路。首先在某个时间干某件事情，某个时间好办，我可以这样，我命令说9点帮我发消息给安安，那么我可以让Jarvis把9点这个时间记录下来，然后从开始运行到结束，一直开一个线程去遍历本地的todo事件，并且对比这个todo时间的执行time跟当前时间的差，如果跟当前时间差了差不多2分钟（注意这里的两分钟指的是这个线程的呼吸时间，这个时间不能太快，太快会把机器类似），我们就执行这个事件。</p>
<p>刚才吃饭去了，ok我们继续写，刚才说到我们可以在接收到指令之后就把这个时间存入本地文件里面，然后有一个巡航的线程会一直去读取然后查询是否有事件，如果满足执行时间要求就执行这个时间，那么问题来了，这个时间是存入数据库好呢还是存入pickle文件好呢，实际上我感觉都一样，考虑到便利应该存入pickel文件更好一些，不不不不，错了错了，还是存入数据库好一点，用mongo存的话，那么每个时间就有一个时间属性，一个名称，重点是名称，这个名称不仅仅是单一的时间名称还可以是一个数组包含多个字段，方便后面Jarvis进行模糊查询，除此之外这个todo collection的doc中还要包含event subject和event receptor，为什么要设计这个，是因为Jarvis做的每一个事情都应该有一个时间的主体和受体，试想一下，有木有时间不存在主体和受体呢？好吧其实这个设计的也没有什么用。但是数据库中以下结构是必须要的：</p>
<figure class="highlight ceylon"><table><tr><td class="code"><pre><div class="line">&#123;</div><div class="line">  <span class="string">'todo_event_name'</span>: [<span class="string">'给安安打电话'</span>, <span class="string">'打电话给安安'</span>],</div><div class="line">  <span class="string">'todo_event_executor'</span>: <span class="string">'command.phone'</span>,</div><div class="line">  <span class="string">'todo_event_time'</span>: datetime.datime&lt;<span class="keyword">object</span>&gt;</div><div class="line"></div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>ok,现在感觉todo时间的存储问题解决了，直接存入mongo，然后开启一个线程每隔两分钟查询一次数据库把当前时间的事件都列出来然后一一去执行。感觉问题解决了有木有，但是问题又来了，怎么把一个函数存入数据库呢？上面写的按照注册名来写其实是不科学的，应该获取不到。接下来我们要做一个实验了。</p>
<blockquote>
<p>我们依旧从上面的巡航机器人代码的开始改，这次要实现的功能是，我过了一分钟之后就把一个代执行的函数存入pkl中，同时存入参数，表示我当前接收到了一个命令然后把命令的执行方法保存下来，在到了执行之间之后再调用它去执行。</p>
</blockquote>
<p>ok,到这里我们的问题已经解决了。我们现在是这样的：所有todo的事件保存到pkl之中，方法只要保存类名和方法名即可，使用Python里面的发射和自省来实现根据类名调用函数。这样的话我开启一个线程不断的读取那个文件，注意为了保证不锁死线程，我们偶数分钟的时候去读取，奇数分钟的时候去存。最后就可以在任意适合牛逼的调用任何方法了！！！！！<br>贴出这个实验代码：</p>
<figure class="highlight python"><table><tr><td class="code"><pre><div class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</div><div class="line"><span class="keyword">from</span> datetime <span class="keyword">import</span> datetime</div><div class="line"><span class="keyword">import</span> logging</div><div class="line"><span class="keyword">import</span> time</div><div class="line"><span class="keyword">from</span> threading <span class="keyword">import</span> Thread</div><div class="line"><span class="keyword">import</span> pickle</div><div class="line"><span class="keyword">import</span> os</div><div class="line"><span class="keyword">from</span> todo.todo <span class="keyword">import</span> ToDoer</div><div class="line"></div><div class="line">logging.basicConfig(level=logging.DEBUG, format=<span class="string">'(%(threadName)-10s) %(message)s'</span>)</div><div class="line"></div><div class="line"></div><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">CruiseBot</span><span class="params">(object)</span>:</span></div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></div><div class="line">        self.name = <span class="string">'Cruise'</span></div><div class="line"></div><div class="line">        self._init_start_time()</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">cruise</span><span class="params">(self)</span>:</span></div><div class="line">        self._main_loop()</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">_init_start_time</span><span class="params">(self)</span>:</span></div><div class="line">        self.start_time = datetime.now()</div><div class="line"></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">_main_loop</span><span class="params">(self)</span>:</span></div><div class="line">        <span class="comment"># this is his main duty job</span></div><div class="line">        threads = []</div><div class="line">        <span class="keyword">while</span> <span class="keyword">True</span>:</div><div class="line">            logging.debug(<span class="string">'&#123;&#125;, now time is: &#123;&#125;'</span>.format(self.name, datetime.now()))</div><div class="line">            time.sleep(<span class="number">5</span>)</div><div class="line"></div><div class="line">            now = datetime.now()</div><div class="line">            delta = (now - self.start_time).seconds</div><div class="line">            print(<span class="string">'delta '</span>, delta)</div><div class="line">            <span class="keyword">if</span> delta == <span class="number">10</span>:</div><div class="line">                <span class="comment"># 10s之后开一个线程执行另外一个事情</span></div><div class="line">                logging.debug(<span class="string">'start execute job 2'</span>)</div><div class="line">                t2 = Thread(name=<span class="string">'bob'</span>, target=self._thread_job_1)</div><div class="line">                t2.start()</div><div class="line">                threads.append(t2)</div><div class="line">            <span class="keyword">if</span> delta == <span class="number">20</span>:</div><div class="line">                <span class="comment"># 20s之后开一个线程执行另外一个事情</span></div><div class="line">                logging.debug(<span class="string">'start execute job 2'</span>)</div><div class="line">                t3 = Thread(name=<span class="string">'cc'</span>, target=self._thread_job_2)</div><div class="line">                t3.start()</div><div class="line">                threads.append(t3)</div><div class="line">            <span class="keyword">if</span> delta == <span class="number">30</span>:</div><div class="line">                <span class="keyword">for</span> t <span class="keyword">in</span> threads:</div><div class="line">                    t.join()</div><div class="line">                <span class="keyword">break</span></div><div class="line"></div><div class="line"><span class="meta">    @staticmethod</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">_thread_job_1</span><span class="params">()</span>:</span></div><div class="line">        obj = &#123;</div><div class="line">            <span class="string">'class_name'</span>: <span class="string">'ToDoer'</span>,</div><div class="line">            <span class="string">'function_name'</span>: <span class="string">'todo_job'</span>,</div><div class="line">            <span class="string">'function_args'</span>: ([<span class="string">'hello'</span>, <span class="string">'fuck'</span>, <span class="string">'shit'</span>, <span class="string">'man'</span>],),</div><div class="line">            <span class="string">'time'</span>: datetime.now()</div><div class="line">        &#125;</div><div class="line">        <span class="keyword">with</span> open(<span class="string">'todo.pkl'</span>, <span class="string">'wb'</span>) <span class="keyword">as</span> f:</div><div class="line">            pickle.dump(obj, f)</div><div class="line">        logging.debug(<span class="string">'todo save into local success!'</span>)</div><div class="line"></div><div class="line"><span class="meta">    @staticmethod</span></div><div class="line">    <span class="function"><span class="keyword">def</span> <span class="title">_thread_job_2</span><span class="params">()</span>:</span></div><div class="line">        <span class="comment"># job3 will open local todo file and execute method inside it</span></div><div class="line"></div><div class="line">        <span class="keyword">if</span> os.path.exists(<span class="string">'todo.pkl'</span>):</div><div class="line">            <span class="keyword">with</span> open(<span class="string">'todo.pkl'</span>, <span class="string">'rb'</span>) <span class="keyword">as</span> f:</div><div class="line">                obj = pickle.load(f)</div><div class="line">            class_name = obj[<span class="string">'class_name'</span>]</div><div class="line">            function_name = obj[<span class="string">'function_name'</span>]</div><div class="line">            function_args = obj[<span class="string">'function_args'</span>]</div><div class="line"></div><div class="line">            c = globals()[class_name]()</div><div class="line">            func = getattr(c, function_name)</div><div class="line">            print(func)</div><div class="line">            func(*function_args)</div><div class="line">            logging.debug(<span class="string">'resume function execute succeed!'</span>)</div><div class="line">        <span class="keyword">else</span>:</div><div class="line">            logging.debug(<span class="string">'file not find.'</span>)</div><div class="line"></div><div class="line"></div><div class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></div><div class="line">    cruise_bot = CruiseBot()</div><div class="line">    cruise_bot.cruise()</div><div class="line"></div><div class="line"></div><div class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</div><div class="line">    main()</div></pre></td></tr></table></figure>
<p>这里我们的ToDoer这个类在module <code>todo/todo.py</code>这个文件中，我们实现import进去，那么我用global这个反射就可以根据类的名字还原成类的对象，今儿找到我们需要的方法在执行它。另外参数的问题也可以轻而易举的搞定。</p>
<p>输出如下：</p>
<figure class="highlight smali"><table><tr><td class="code"><pre><div class="line">(MainThread) Cruise, now time is: 2017-04-28 14:43:00.268181</div><div class="line">delta  5</div><div class="line">(MainThread) Cruise, now time is: 2017-04-28 14:43:05.270000</div><div class="line">delta  10</div><div class="line">(MainThread) start<span class="built_in"> execute </span>job 2</div><div class="line">(MainThread) Cruise, now time is: 2017-04-28 14:43:10.274169</div><div class="line">(bob       ) todo save into local success!</div><div class="line">delta  15</div><div class="line">(MainThread) Cruise, now time is: 2017-04-28 14:43:15.274941</div><div class="line">delta  20</div><div class="line">(MainThread) start<span class="built_in"> execute </span>job 2</div><div class="line">(MainThread) Cruise, now time is: 2017-04-28 14:43:20.278646</div><div class="line">&lt;function ToDoer.todo_job at 0x10b36f400&gt;</div><div class="line">['hello', 'fuck', 'shit', 'man']</div><div class="line">I am executed!!!!!!!</div><div class="line">(cc        ) resume function<span class="built_in"> execute </span>succeed!</div><div class="line">delta  25</div><div class="line">(MainThread) Cruise, now time is: 2017-04-28 14:43:25.284144</div><div class="line">delta  30</div></pre></td></tr></table></figure>
<p>好了，本次列车到此结束，欢迎下次乘坐。</p>

      
    </div>
    <footer class="article-footer">
      
        <div id="donation_div"></div>

<script src="/js/vdonate.js"></script>
<script>
var a = new Donate({
  title: '骚年，加个好友打赏一下啊，现在连泡面都吃不起了啊', // 可选参数，打赏标题
  btnText: '打赏支持', // 可选参数，打赏按钮文字
  el: document.getElementById('donation_div'),
  wechatImage: 'https://i.loli.net/2017/09/27/59cb048ba6838.jpeg',
  alipayImage: 'https://i.loli.net/2017/09/27/59cb049cd0951.jpeg'
});
</script>
      
      
        
	<div id="comment">
		<!-- 来必力City版安装代码 -->
		<div id="lv-container" data-id="city" data-uid="MTAyMC8zMDA5MC82NjQ1">
		<script type="text/javascript">
		   (function(d, s) {
		       var j, e = d.getElementsByTagName(s)[0];

		       if (typeof LivereTower === 'function') { return; }

		       j = d.createElement(s);
		       j.src = 'https://cdn-city.livere.com/js/embed.dist.js';
		       j.async = true;

		       e.parentNode.insertBefore(j, e);
		   })(document, 'script');
		</script>
		<noscript>为正常使用来必力评论功能请激活JavaScript</noscript>
		</div>
		<!-- City版安装代码已完成 -->
	</div>



      
      
    </footer>
  </div>
  
    
<nav id="article-nav">
  
    <a href="/2017/05/08/Reinforcement-从入门到上天Series-1/" id="article-nav-newer" class="article-nav-link-wrap">
      <strong class="article-nav-caption">上一篇</strong>
      <div class="article-nav-title">
        
          ReinforcementLearning从入门到上天Series 1
        
      </div>
    </a>
  
  
    <a href="/2017/04/14/2017-3-26-ubuntu云服务器无法访问https折腾/" id="article-nav-older" class="article-nav-link-wrap">
      <strong class="article-nav-caption">下一篇</strong>
      <div class="article-nav-title"></div>
    </a>
  
</nav>

  
</article>

<!-- Table of Contents -->

  <aside id="toc-sidebar">
    <div id="toc" class="toc-article">
    <strong class="toc-title">文章目录</strong>
    
        <ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#继上一篇多线程文章之后，继续研究Python多线程并发"><span class="nav-number">1.</span> <span class="nav-text">继上一篇多线程文章之后，继续研究Python多线程并发</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#抛弃multiporcess使用Threading"><span class="nav-number">2.</span> <span class="nav-text">抛弃multiporcess使用Threading</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Threading还能干什么"><span class="nav-number">3.</span> <span class="nav-text">Threading还能干什么</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#进一步思考"><span class="nav-number">4.</span> <span class="nav-text">进一步思考</span></a></li></ol>
    
    </div>
  </aside>
</section>
        
      </div>
      
      <footer id="footer">
  

  <div class="container">
      	<div class="row">
	      <p> Powered by <a href="http://www.luoli-luoli.com/" target="_blank">萝莉萝莉</a> and <a href="http://www.luoli-luoli.com/sia" target="_blank">Sia</a> </p>
	      <p id="copyRightEn">Copyright &copy; 2017 - 2018 Jin Tian All Rights Reserved.</p>
	      
	      
    		<p class="busuanzi_uv">
				访客数 : <span id="busuanzi_value_site_uv"></span> |  
				访问量 : <span id="busuanzi_value_site_pv"></span>
		    </p>
  		   
		</div>

		
  </div>
</footer>


<!-- min height -->

<script>
    var wrapdiv = document.getElementById("wrap");
    var contentdiv = document.getElementById("content");
    var allheader = document.getElementById("allheader");

    wrapdiv.style.minHeight = document.body.offsetHeight + "px";
    if (allheader != null) {
      contentdiv.style.minHeight = document.body.offsetHeight - allheader.offsetHeight - document.getElementById("footer").offsetHeight + "px";
    } else {
      contentdiv.style.minHeight = document.body.offsetHeight - document.getElementById("footer").offsetHeight + "px";
    }
</script>
    </div>
    <!-- <nav id="mobile-nav">
  
    <a href="/" class="mobile-nav-link">Home</a>
  
    <a href="/archives" class="mobile-nav-link">Archives</a>
  
    <a href="/categories" class="mobile-nav-link">Categories</a>
  
    <a href="/tags" class="mobile-nav-link">Tags</a>
  
    <a href="/about" class="mobile-nav-link">About</a>
  
    <a href="http://luoli-luoli.com/chat" class="mobile-nav-link">Chat</a>
  
</nav> -->
    

<!-- mathjax config similar to math.stackexchange -->

<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    tex2jax: {
      inlineMath: [ ['$','$'], ["\\(","\\)"] ],
      processEscapes: true
    }
  });
</script>

<script type="text/x-mathjax-config">
    MathJax.Hub.Config({
      tex2jax: {
        skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
      }
    });
</script>

<script type="text/x-mathjax-config">
    MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax(), i;
        for(i=0; i < all.length; i += 1) {
            all[i].SourceElement().parentNode.className += ' has-jax';
        }
    });
</script>

<script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>


  <link rel="stylesheet" href="/fancybox/jquery.fancybox.css">
  <script src="/fancybox/jquery.fancybox.pack.js"></script>


<script src="/js/scripts.js"></script>




  <script src="/js/dialog.js"></script>








	<div style="display: none;">
    <script src="https://s95.cnzz.com/z_stat.php?id=1260716016&web_id=1260716016" language="JavaScript"></script>
  </div>



	<script async src="//dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js">
	</script>






  </div>

  <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="display: none;">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h2 class="modal-title" id="myModalLabel">设置</h2>
      </div>
      <hr style="margin-top:0px; margin-bottom:0px; width:80%; border-top: 3px solid #000;">
      <hr style="margin-top:2px; margin-bottom:0px; width:80%; border-top: 1px solid #000;">


      <div class="modal-body">
          <div style="margin:6px;">
            <a data-toggle="collapse" data-parent="#accordion" href="#collapseOne" onclick="javascript:setFontSize();" aria-expanded="true" aria-controls="collapseOne">
              正文字号大小
            </a>
          </div>
          <div id="collapseOne" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingOne">
          <div class="panel-body">
            您已调整页面字体大小
          </div>
        </div>
      


          <div style="margin:6px;">
            <a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" onclick="javascript:setBackground();" aria-expanded="true" aria-controls="collapseTwo">
              夜间护眼模式
            </a>
        </div>
          <div id="collapseTwo" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingTwo">
          <div class="panel-body">
            夜间模式已经开启，再次单击按钮即可关闭 
          </div>
        </div>

        <div>
            <a data-toggle="collapse" data-parent="#accordion" href="#collapseThree" aria-expanded="true" aria-controls="collapseThree">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;关 于&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</a>
        </div>
         <div id="collapseThree" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingThree">
          <div class="panel-body">
            Jin Tian
          </div>
          <div class="panel-body">
            Copyright © 2018 Jintian All Rights Reserved.
          </div>
        </div>
      </div>


      <hr style="margin-top:0px; margin-bottom:0px; width:80%; border-top: 1px solid #000;">
      <hr style="margin-top:2px; margin-bottom:0px; width:80%; border-top: 3px solid #000;">
      <div class="modal-footer">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
      </div>
    </div>
  </div>
</div>
  
  <a id="rocket" href="#top" class=""></a>
  <script type="text/javascript" src="/js/totop.js?v=1.0.0" async=""></script>
  
    <a id="menu-switch"><i class="fa fa-bars fa-lg"></i></a>
  
</body>
</html>